const http = require('http');
const WebSocket = require('ws');

// 测试配置
const CONFIG = {
    server: {
        host: 'localhost',
        port: 3000,
        protocol: 'http'
    },

    // 测试用户信息
    testUser: {
        mobile: '17091271111',
        password: '123456',
        passwordHash: 'e10adc3949ba59abbe56e057f20f883e' // 123456的MD5
    },

    // 测试角色信息
    testCharacter: {
        name: '测试角色',
        sex: 1, // 1:男, 0:女
        roleType: 1, // 1:武士, 2:文人, 3:异师
        headIndex: 2
    }
};

// 测试下注数据
const testBets = [
    {
        act_id: 1336,
        betType: 1, // 大
        betAmount: 1000,
        currencyType: 1, // 金币
    },
    {
        act_id: 1336,
        betType: 2, // 小
        betAmount: 500,
        currencyType: 1, // 金币
    },
    {
        act_id: 1336,
        betType: 3, // 单
        betAmount: 800,
        currencyType: 2, // 银币
    },
    {
        act_id: 1336,
        betType: 4, // 双
        betAmount: 1200,
        currencyType: 2, // 银币
    },
    {
        act_id: 1336,
        betType: 5, // 豹子
        betAmount: 2000,
        currencyType: 1, // 金币
    },
];

class CasinoBetTester {
    constructor() {
        this.token = null;
        this.userId = null;
        this.characters = [];
        this.selectedCharacter = null;
        this.ws = null;
        this.testResults = [];
    }

    async runFullTest() {
        console.log('🎲 开始测试娱乐城下注总额计算功能...\n');

        try {
            // 1. HTTP登录
            console.log('🔐 步骤1: HTTP登录测试...');
            if (!await this.testHttpLogin()) {
                throw new Error('HTTP登录失败');
            }

            // 2. WebSocket连接
            console.log('🔌 步骤2: WebSocket连接测试...');
            if (!await this.testWebSocketConnection()) {
                throw new Error('WebSocket连接失败');
            }

            // 3. 查询角色列表
            console.log('📋 步骤3: 查询角色列表...');
            if (!await this.testQueryCharacters()) {
                throw new Error('查询角色列表失败');
            }

            // 4. 选择角色
            console.log('🎯 步骤4: 选择角色...');
            if (!await this.testSelectCharacter()) {
                throw new Error('选择角色失败');
            }

            // 5. 测试下注功能
            console.log('💰 步骤5: 测试下注功能...');
            await this.testCasinoBetting();

            // 6. 断开连接
            console.log('🔌 步骤6: 断开WebSocket连接...');
            await this.testDisconnect();

            // 7. 打印测试结果
            this.printTestResults();

        } catch (error) {
            console.error('❌ 测试过程中发生错误:', error.message);
            this.printTestResults();
        }
    }

    async testHttpLogin() {
        try {
            // 先尝试注册用户
            const registerResult = await this.registerUser();
            console.log('📝 用户注册结果:', registerResult);

            // 登录用户
            const loginResult = await this.loginUser();
            if (loginResult.code === 0) {
                this.token = loginResult.data.accessToken;
                this.userId = loginResult.data.userId;
                console.log('✅ 登录成功: userId=' + this.userId + ', token=' + this.token.substring(0, 20) + '...');
                this.addTestResult('HTTP登录', true, '用户ID: ' + this.userId);
                return true;
            } else {
                console.log('❌ 登录失败:', loginResult.msg);
                this.addTestResult('HTTP登录', false, loginResult.msg);
                return false;
            }
        } catch (error) {
            console.error('❌ HTTP登录异常:', error.message);
            this.addTestResult('HTTP登录', false, error.message);
            return false;
        }
    }

    async registerUser() {
        return new Promise((resolve, reject) => {
            const postData = JSON.stringify({
                mobile: CONFIG.testUser.mobile,
                pwd: CONFIG.testUser.passwordHash,
                captcha: '123456'
            });

            const options = {
                hostname: CONFIG.server.host,
                port: CONFIG.server.port,
                path: '/user-service/user/register',
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Content-Length': Buffer.byteLength(postData)
                }
            };

            const req = http.request(options, (res) => {
                let data = '';
                res.on('data', (chunk) => data += chunk);
                res.on('end', () => {
                    try {
                        const result = JSON.parse(data);
                        resolve(result);
                    } catch (error) {
                        reject(error);
                    }
                });
            });

            req.on('error', reject);
            req.write(postData);
            req.end();
        });
    }

    async loginUser() {
        return new Promise((resolve, reject) => {
            const postData = JSON.stringify({
                mobile: CONFIG.testUser.mobile,
                pwd: CONFIG.testUser.passwordHash
            });

            const options = {
                hostname: CONFIG.server.host,
                port: CONFIG.server.port,
                path: '/user-service/user/login',
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Content-Length': Buffer.byteLength(postData)
                }
            };

            const req = http.request(options, (res) => {
                let data = '';
                res.on('data', (chunk) => data += chunk);
                res.on('end', () => {
                    try {
                        const result = JSON.parse(data);
                        resolve(result);
                    } catch (error) {
                        reject(error);
                    }
                });
            });

            req.on('error', reject);
            req.write(postData);
            req.end();
        });
    }

    async testWebSocketConnection() {
        try {
            const wsUrl = `ws://${CONFIG.server.host}:${CONFIG.server.port}`;
            this.ws = new WebSocket(wsUrl);

            return new Promise((resolve) => {
                this.ws.on('open', () => {
                    console.log('✅ WebSocket连接成功');
                    this.addTestResult('WebSocket连接', true, '连接建立成功');
                    resolve(true);
                });

                this.ws.on('error', (error) => {
                    console.error('❌ WebSocket连接失败:', error.message);
                    this.addTestResult('WebSocket连接', false, error.message);
                    resolve(false);
                });

                // 设置连接超时
                setTimeout(() => {
                    if (this.ws.readyState === WebSocket.CONNECTING) {
                        console.error('❌ WebSocket连接超时');
                        this.addTestResult('WebSocket连接', false, '连接超时');
                        resolve(false);
                    }
                }, 5000);
            });
        } catch (error) {
            console.error('❌ WebSocket连接异常:', error.message);
            this.addTestResult('WebSocket连接', false, error.message);
            return false;
        }
    }

    async testQueryCharacters() {
        try {
            return new Promise((resolve) => {
                const message = {
                    c: 3, // 查询角色列表
                    userId: this.userId
                };

                this.ws.send(JSON.stringify(message));

                const timeout = setTimeout(() => {
                    console.log('❌ 查询角色列表超时');
                    this.addTestResult('查询角色列表', false, '请求超时');
                    resolve(false);
                }, 5000);

                this.ws.once('message', (data) => {
                    clearTimeout(timeout);
                    try {
                        const response = JSON.parse(data.toString());
                        if (response.code === 0 && response.data) {
                            this.characters = response.data;
                            console.log('✅ 查询成功，共' + this.characters.length + '个角色');
                            this.addTestResult('查询角色列表', true, '获取' + this.characters.length + '个角色');
                            resolve(true);
                        } else {
                            console.log('❌ 查询角色列表失败:', response.msg);
                            this.addTestResult('查询角色列表', false, response.msg);
                            resolve(false);
                        }
                    } catch (error) {
                        console.error('❌ 解析角色列表响应失败:', error.message);
                        this.addTestResult('查询角色列表', false, error.message);
                        resolve(false);
                    }
                });
            });
        } catch (error) {
            console.error('❌ 查询角色列表异常:', error.message);
            this.addTestResult('查询角色列表', false, error.message);
            return false;
        }
    }

    async testSelectCharacter() {
        try {
            if (this.characters.length === 0) {
                console.log('❌ 没有可选择的角色');
                this.addTestResult('选择角色', false, '没有可选择的角色');
                return false;
            }

            // 选择第一个角色
            const character = this.characters[0];
            this.selectedCharacter = character;

            return new Promise((resolve) => {
                const message = {
                    c: 4, // 选择角色
                    userId: this.userId,
                    characterId: character.id
                };

                this.ws.send(JSON.stringify(message));

                const timeout = setTimeout(() => {
                    console.log('❌ 选择角色超时');
                    this.addTestResult('选择角色', false, '请求超时');
                    resolve(false);
                }, 5000);

                this.ws.once('message', (data) => {
                    clearTimeout(timeout);
                    try {
                        const response = JSON.parse(data.toString());
                        if (response.code === 0) {
                            console.log('✅ 角色选择成功: ' + character.name + ' (ID: ' + character.id + ')');
                            this.addTestResult('选择角色', true, '选择角色: ' + character.name);
                            resolve(true);
                        } else {
                            console.log('❌ 选择角色失败:', response.msg);
                            this.addTestResult('选择角色', false, response.msg);
                            resolve(false);
                        }
                    } catch (error) {
                        console.error('❌ 解析选择角色响应失败:', error.message);
                        this.addTestResult('选择角色', false, error.message);
                        resolve(false);
                    }
                });
            });
        } catch (error) {
            console.error('❌ 选择角色异常:', error.message);
            this.addTestResult('选择角色', false, error.message);
            return false;
        }
    }

    async testCasinoBetting() {
        try {
            // 1. 获取游戏信息，查看初始状态
            console.log('📊 1. 获取初始游戏信息...');
            const initialInfo = await this.getDiceGameInfo();
            this.displayGameInfo('初始下注总额', initialInfo);

            // 2. 执行下注操作
            console.log('💰 2. 开始执行下注操作...');
            for (let i = 0; i < testBets.length; i++) {
                const bet = testBets[i];
                console.log(`下注 ${i + 1}: 类型=${bet.betType}, 金额=${bet.betAmount}, 货币=${bet.currencyType === 1 ? '金币' : '银币'}`);

                const result = await this.placeDiceBet(bet);
                if (result.code === 0) {
                    console.log(`  ✅ 下注成功`);
                } else {
                    console.log(`  ❌ 下注失败: ${result.msg}`);
                }

                // 等待一下，避免下注过快
                await this.sleep(100);
            }

            // 3. 再次获取游戏信息，查看下注后的状态
            console.log('\n📊 3. 获取下注后的游戏信息...');
            await this.sleep(500); // 等待数据更新
            const updatedInfo = await this.getDiceGameInfo();

            this.displayGameInfo('下注后下注总额', updatedInfo);

            // 4. 验证下注总额是否正确
            console.log('🔍 4. 验证下注总额计算...');
            const expectedTotals = {
                sumbaozigold: 2000,
                sumbaozisliver: 0,
                sumdagold: 1000,
                sumdasliver: 0,
                sumdangold: 0,
                sumdansliver: 800,
                sumshuanggold: 0,
                sumshuangsliver: 1200,
                sumxiaogold: 500,
                sumxiaosliver: 0,
            };

            let allCorrect = true;
            for (const [key, expected] of Object.entries(expectedTotals)) {
                const actual = updatedInfo[key];
                if (actual === expected) {
                    console.log(`  ✅ ${key}: ${actual} (正确)`);
                } else {
                    console.log(`  ❌ ${key}: ${actual} (期望: ${expected})`);
                    allCorrect = false;
                }
            }

            if (allCorrect) {
                console.log('\n🎉 所有下注总额计算正确！');
                this.addTestResult('下注总额验证', true, '所有下注总额计算正确');
            } else {
                console.log('\n⚠️  部分下注总额计算有误，请检查实现。');
                this.addTestResult('下注总额验证', false, '部分下注总额计算有误');
            }

        } catch (error) {
            console.error('❌ 测试下注功能时发生错误:', error.message);
            this.addTestResult('下注功能测试', false, error.message);
        }
    }

    displayGameInfo(title, info) {
        console.log(title + ':');
        console.log(`  豹子金币: ${info.sumbaozigold}`);
        console.log(`  豹子银币: ${info.sumbaozisliver}`);
        console.log(`  大金币: ${info.sumdagold}`);
        console.log(`  大银币: ${info.sumdasliver}`);
        console.log(`  单金币: ${info.sumdangold}`);
        console.log(`  单银币: ${info.sumdansliver}`);
        console.log(`  双金币: ${info.sumshuanggold}`);
        console.log(`  双银币: ${info.sumshuangsliver}`);
        console.log(`  小金币: ${info.sumxiaogold}`);
        console.log(`  小银币: ${info.sumxiaosliver}\n`);
    }

    async getDiceGameInfo() {
        return new Promise((resolve, reject) => {
            const message = {
                c: 1332, // 获取骰子游戏信息
                userId: this.userId,
                characterId: this.selectedCharacter.id,
            };

            this.ws.send(JSON.stringify(message));

            const timeout = setTimeout(() => {
                reject(new Error('获取游戏信息超时'));
            }, 5000);

            this.ws.once('message', (data) => {
                clearTimeout(timeout);
                try {
                    const response = JSON.parse(data.toString());
                    resolve(response);
                } catch (error) {
                    reject(error);
                }
            });
        });
    }

    async placeDiceBet(betData) {
        return new Promise((resolve, reject) => {
            const message = {
                ...betData,
                userId: this.userId,
                characterId: this.selectedCharacter.id,
            };

            this.ws.send(JSON.stringify(message));

            const timeout = setTimeout(() => {
                reject(new Error('下注请求超时'));
            }, 5000);

            this.ws.once('message', (data) => {
                clearTimeout(timeout);
                try {
                    const response = JSON.parse(data.toString());
                    resolve(response);
                } catch (error) {
                    reject(error);
                }
            });
        });
    }

    async testDisconnect() {
        try {
            if (this.ws) {
                this.ws.close();
                console.log('✅ WebSocket连接已关闭');
                this.addTestResult('断开连接', true, '连接已关闭');
            }
        } catch (error) {
            console.error('❌ 断开连接失败:', error.message);
            this.addTestResult('断开连接', false, error.message);
        }
    }

    addTestResult(testName, success, details) {
        this.testResults.push({
            name: testName,
            success,
            details,
            timestamp: new Date()
        });
    }

    printTestResults() {
        console.log('\n============================================================');
        console.log('📊 娱乐城下注测试结果汇总');
        console.log('============================================================');

        this.testResults.forEach((result, index) => {
            const status = result.success ? '✅' : '❌';
            const time = result.timestamp.toISOString();
            console.log(`${status} 测试${index + 1}: ${result.name}`);
            console.log(`   结果: ${result.success ? '通过' : '失败'}`);
            console.log(`   详情: ${result.details}`);
            console.log(`   时间: ${time}\n`);
        });

        const totalTests = this.testResults.length;
        const passedTests = this.testResults.filter(r => r.success).length;
        const failedTests = totalTests - passedTests;
        const successRate = ((passedTests / totalTests) * 100).toFixed(1);

        console.log('============================================================');
        console.log('📈 测试统计:');
        console.log(`   总计: ${totalTests} 个测试`);
        console.log(`   通过: ${passedTests} 个`);
        console.log(`   失败: ${failedTests} 个`);
        console.log(`   成功率: ${successRate}%`);

        if (failedTests === 0) {
            console.log('\n🎉 所有测试通过！娱乐城下注功能测试成功！');
        } else {
            console.log('\n⚠️  部分测试失败，请检查相关功能。');
        }
        console.log('============================================================');
    }

    sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
}

// 运行测试
if (require.main === module) {
    const tester = new CasinoBetTester();
    tester.runFullTest().catch(console.error);
}

module.exports = { CasinoBetTester }; 